<!DOCTYPE html>
<html>

<?php

use Wgx\Admin\Com\AdminMenuRightsUtil;
use Wgx\Admin\Com\Crud\Crud;
use Wgx\Admin\Com\Crud\CrudField;
use Wgx\Admin\Com\Crud\ListPageSearchInputBase;
use Wgx\Admin\Entity\AdminToMenuEntity;
use PhpYes\Apps;

/** @var Crud $crud */
$crud = empty($this->data['crud']) ? null : $this->data['crud'];
if (empty($crud)) {
    // 这里抛出异常发生在 Http Headers 输出之后，会破坏正在返回给客户端的报文，
    // 但这种情况本不应该发生，所以这里还是选择抛出一个异常，为了反馈给开发人员，以便开发人员赶紧改正
    throw new \InvalidArgumentException('请传递crud');
}

?>

<head>
  <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/meta.html.php'); ?>
  <title>
    <?php
    $prefix = \PhpYes\Apps::getAdminPageTitlePrefix();
    $menuName = '';
    $currMenu = AdminMenuRightsUtil::getSingleObj()->getCurrentMenu();
    if ($currMenu) {
        $menuName = $currMenu->getName();
    }
    $opName = '列表';
    echo "{$prefix} - {$menuName} - {$opName}";
    ?>
  </title>
  <meta name="description" content="index" />
  <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/css.html.php'); ?>
  <!-- <link rel="stylesheet" href="/wgx_admin_static/DataTables/DataTables-1.10.21/css/jquery.dataTables.min.css"> -->
  <!-- <link rel="stylesheet" href="/wgx_admin_static/DataTables/Buttons-1.6.2/css/buttons.dataTables.min.css"> -->
  <!-- <link rel="stylesheet" href="/wgx_admin_static/DataTables/Select-1.3.1/css/select.dataTables.min.css"> -->
  <link rel="stylesheet" href="/wgx_admin_static/admin/wgxadmin.dataTables.css">
  <?php
  $cssFileMap = $crud->getFileMap(Crud::PageListPage, Crud::FileCssFile);
  if ($cssFileMap) {
      foreach ($cssFileMap as $file => $flag) {
          if ($flag) {
              echo '<link rel="stylesheet" href="' . $file . '" />' . "\n";
          }
      }
  }
  ?>
  <style>
    <?php
    $cssInlineFileMap = $crud->getFileMap(Crud::PageListPage, Crud::FileCssInline);
    if ($cssInlineFileMap) {
        foreach ($cssInlineFileMap as $file => $flag) {
            if ($flag) {
                require $file ;
            }
        }
    }
    ?>
  </style>
</head>

<body>
  <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/topbar.html.php'); ?>
  <div id="main-container" class="main-container">
    <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/sidebar.html.php'); ?>
    <div id="main-content" class="main-content">
      <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/breadcrumb.html.php'); ?>
      <div id="page-content" class="page-content">
        <div class="wgx_table_wrapper">
          <div class="table_searchbar">
            <?php
            $selectOnlineFieldArr = array();
            $fieldMap = $crud->getLpSearchFieldMap();
            if ($fieldMap) {
                /**
                 * @var string $fieldName
                 * @var ListPageSearchInputBase $inputWidget
                 */
                foreach ($fieldMap as $fieldName => $inputWidget) {
                    $inputHtml = '';
                    $inputType = $inputWidget->getInputType();
                    switch ($inputType) {
                        case ListPageSearchInputBase::InputText:
                        case ListPageSearchInputBase::InputNumber:
                        case ListPageSearchInputBase::InputTel:
                        case ListPageSearchInputBase::InputEmail:
                            /** @var \Wgx\Admin\Com\Crud\ListPageSearchInput\InputInputBase $inputWidget */
                            $placeholder = $inputWidget->getPlaceholder();
                            $placeholder = empty($placeholder) ? null : trim($placeholder);
                            $initialValue = $inputWidget->getInitialValue();
                            $initialValue = isset($initialValue) ? trim(strval($initialValue)) : '';
                            $className = $inputWidget->getClassName();
                            $className = empty($className) ? null : trim($className);
                            $specParam = $inputWidget->getSpecParam();
                            $specParam = empty($specParam) ? null : trim($specParam);
                            $inputHtml = '<input type="' . $inputWidget->getType() . '"'
                                . ' class="input' . (empty($className) ? '' : " {$className}") . '"'
                                . ' name="' . $fieldName . '"'
                                . ' value="' . $initialValue . '"'
                                . (empty($placeholder) ? '' : ' placeholder="' . $placeholder . '"')
                                . (empty($specParam) ? '' : " {$specParam}")
                                . ' />';
                            break;
                        case ListPageSearchInputBase::InputSelect:
                            /** @var \Wgx\Admin\Com\Crud\ListPageSearchInput\InputSelect $inputWidget */
                            $initialValue = $inputWidget->getInitialValue();
                            $className = $inputWidget->getClassName();
                            $className = empty($className) ? null : trim($className);
                            $specParam = $inputWidget->getSpecParam();
                            $specParam = empty($specParam) ? null : trim($specParam);
                            $optionMap = $inputWidget->getOptionMap();
                            $inputHtml = '<select'
                                . ' class="input' . (empty($className) ? '' : " {$className}") . '"'
                                . ' name="' . $fieldName . '"'
                                . (empty($specParam) ? '' : " {$specParam}")
                                . '>';
                            if (empty($optionMap)) {
                                $inputHtml .= '<option value="">空空空</option>';
                            } else {
                                foreach ($optionMap as $k => $v) {
                                    $inputHtml .= '<option value="' . $k . '"' . (isset($initialValue) && $initialValue == $k ? ' selected' : '') . '>' . $v . '</option>';
                                }
                            }
                            $inputHtml .= '</select>';
                            break;
                        case ListPageSearchInputBase::InputSelectOnline:
                            /** @var \Wgx\Admin\Com\Crud\ListPageSearchInput\InputSelectOnline $inputWidget */
                            $className = $inputWidget->getClassName();
                            $className = empty($className) ? null : trim($className);
                            $specParam = $inputWidget->getSpecParam();
                            $specParam = empty($specParam) ? null : trim($specParam);
                            $inputHtml = '<div class="selectonline' . (empty($className) ? '' : " {$className}") . '"'
                                . (empty($specParam) ? '' : " {$specParam}")
                                . '>';
                            $inputHtml .= '<select name="' . $fieldName . '">';
                            $inputHtml .= '<option></option>';
                            $inputHtml .= '</select>';
                            $inputHtml .= '</div>';
                            $selectOnlineFieldArr[] = array(
                                'fieldName' => $fieldName,
                                'label' => $inputWidget->getLabel(),
                                'url' => $inputWidget->getUrl(),
                                'searchFieldName' => $inputWidget->getSearchFieldName(),
                                'placeholder' => $inputWidget->getPlaceholder(),
                                'width' => $inputWidget->getWidth(),
                                'itemConverter' => $inputWidget->getItemConverter(),
                                'limit' => $inputWidget->getLimit(),
                                'orderFieldName' => $inputWidget->getOrderFieldName(),
                                'orderDirection' => $inputWidget->getOrderDirection(),
                            );
                            break;
                        case ListPageSearchInputBase::InputCustomize:
                            /** @var \Wgx\Admin\Com\Crud\ListPageSearchInput\InputCustomize $inputWidget */
                            $specParam = $inputWidget->getSpecParam();
                            $inputHtml = empty($specParam) ? '' : trim($specParam);
                            break;
                        default:
                            $inputHtml = '';
                            break;
                    }
                    echo '<div class="search_field field_' . trim($fieldName) . '"'
                        . ' data-fieldname="' . $fieldName . '"'
                        . ' data-inputtype="' . $inputType . '"'
                        . '>'
                        . '<label>' . '<span class="label">' . $inputWidget->getLabel() . ':</span>' . $inputHtml . '</label>'
                        . '</div>' . "\n";
                }
                echo '<button class="operate op-search"><i class="fas fa-search"></i> 搜索</button>';
            }

            $canExport = false;
            $fieldMap = $crud->getFieldMap();
            /**
             * @var string $fieldName
             * @var CrudField $field
             */
            foreach ($fieldMap as $fieldName => $field) {
                $showIn = intval($field->getShowIn());
                if (($showIn & CrudField::ShowInExport) > 0) {
                    $canExport = true;
                    break;
                }
            }
            if ($canExport) {
                $exportUrl = \PhpYes\Apps::getReqPath() . '?_op_=export';
                echo '<a class="operate op-export" href="' . $exportUrl . '" target="_blank" rel="noopener noreferrer"><i class="fas fa-file-download"></i> 导出</a>';
            }
            ?>
          </div>
          <div class="table_toolbar">
            <?php
            $rights = AdminMenuRightsUtil::getSingleObj()->getCurrentRights();
            if ($rights) {
                if (($rights & AdminToMenuEntity::RightCreate) > 0) {
                    $createUrl = \PhpYes\Apps::getReqPath() . '?_op_=editpage&id=0';
                    $target = $crud->getPageDisplayTarget(Crud::PageEditPage);
                    $width = $crud->getPageDisplayWidth(Crud::PageEditPage);
                    $height = $crud->getPageDisplayHeight(Crud::PageEditPage);
                    if (empty($target)) {
                        $target = '_blank';
                    }
                    echo '<a class="operate op-create" href="' . $createUrl . '"'
                        . ($target == 'layer' ? '' : ' target="' . $target . '"')
                        . ' title="新增"'
                        . ' data-target="' . $target . '"'
                        . ' data-width="' . $width . '"'
                        . ' data-height="' . $height . '"'
                        . '><i class="fas fa-plus"></i> 新增</a>';
                }
                if (($rights & AdminToMenuEntity::RightDelete) > 0) {
                    echo '<button class="operate op-delete-multi" title="删除选中行" disabled><i class="far fa-trash-alt"></i> 删除</button>';
                }
            }
            ?>
          </div>
          <table id="page_data_table"></table>
        </div>
      </div>
    </div>
  </div>

  <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/footer.html.php'); ?>
  <?php require \PhpYes\Apps::render()->getPage('admin_page_parts/js.html.php'); ?>
  <script src="/wgx_admin_static/DataTables/DataTables-1.10.21/js/jquery.dataTables.min.js"></script>
  <script src="/wgx_admin_static/DataTables/Buttons-1.6.2/js/dataTables.buttons.min.js"></script>
  <script src="/wgx_admin_static/DataTables/Buttons-1.6.2/js/buttons.colVis.min.js"></script>
  <script src="/wgx_admin_static/DataTables/Buttons-1.6.2/js/buttons.html5.min.js"></script>
  <script src="/wgx_admin_static/DataTables/Buttons-1.6.2/js/buttons.print.min.js"></script>
  <script src="/wgx_admin_static/DataTables/Select-1.3.1/js/dataTables.select.min.js"></script>
  <script src="/wgx_admin_static/layer/3.5.1/layer.js"></script>
  <?php
  if ($selectOnlineFieldArr && count($selectOnlineFieldArr) > 0) {
      echo '<link rel="stylesheet" href="/wgx_admin_static/select2/4.0.13/css/select2.min.css" />' . "\n";
      echo '<script src="/wgx_admin_static/select2/4.0.13/js/select2.full.min.js"></script>' . "\n";
      echo '<script src="/wgx_admin_static/select2/4.0.13/js/i18n/zh-CN.js"></script>' . "\n";
  }
  ?>
  <?php
  $jsFileMap = $crud->getFileMap(Crud::PageListPage, Crud::FileJsFile);
  if ($jsFileMap) {
      foreach ($jsFileMap as $file => $flag) {
          if ($flag) {
              echo '<script src="' . $file . '"></script>' . "\n";
          }
      }
  }
  ?>
  <script>
    var getSearchbarSearchData;
    var pageDataTable;
    jQuery(function ($) {
      <?php
        if ($selectOnlineFieldArr && count($selectOnlineFieldArr) > 0) {
            echo <<<'REGISTERSELECTONLINE'

var registerSelectOnline = function (fieldName, url, searchFieldName, placeholder, width, itemConverter, limit, orderFieldName, orderDirection) {
  fieldName = fieldName && fieldName.trim() || null;
  if (!fieldName) { return; }
  url = url && url.trim() || null;
  if (!url) { return; }
  searchFieldName = searchFieldName && searchFieldName.trim() || null;
  if (!searchFieldName) {
    return;
  }
  var selector = '.wgx_table_wrapper .table_searchbar .search_field.field_' + fieldName + ' .selectonline select';

  placeholder = placeholder && placeholder.trim() || null;
  if (!placeholder) {
    placeholder = '请选择';
  }
  width = width && width.trim() || null;

  limit = limit && parseInt(limit) || 0;
  if (!limit) {
    limit = 10;
  }

  orderFieldName = orderFieldName && orderFieldName.trim() || '';
  orderDirection = orderDirection && parseInt(orderDirection) || 0;

  $(selector).select2({
    language: 'zh-CN',
    // theme: '',
    width: width,
    // placeholder: { // 本想这样配置来搞定默认选中，奈何 select2 的行为不是自己想要的，或许 select2 在这个地方有 bug
    //   id: defaultSelVal,
    //   text: defaultSelTxt
    // },
    placeholder: placeholder,
    allowClear: true,
    // dropdownCssClass: '',
    // dropdownAutoWidth: true,
    // templateResult: '',
    // escapeMarkup: '',
    // selectionCssClass: '',
    // templateSelection: '',
    // selectOnClose: false,
    // minimumInputLength: '',
    // maximumInputLength: '',
    ajax: {
      delay: 500,
      method: 'GET',
      url: url,
      // contentType: 'application/json; charset=UTF-8',
      data: function (params) {
        // console.log(params);
        var page = params.page && parseInt(params.page) || 0;
        if (page < 1) { page = 1; }
        var offset = limit * (page - 1);
        var myReq = { _limit: limit, _offset: offset, _orderFieldName: orderFieldName, _orderDirection: orderDirection };
        myReq[searchFieldName] = params.term && params.term.trim() || '';
        return myReq;
      },
      dataType: 'json',
      // beforeSend: function (jqXHR, settings) { },
      // complete: function (jqXHR, textStatus) { },
      processResults: function (data, params) { // 阅读 select2.js 的源代码，发现 processResults 用在 success 回调中
        // console.log(params);
        if (data && data.code && parseInt(data.code) < 400) {
          var total = data && data.data && data.data.total && parseInt(data.data.total) || 0;
          var rspData = data && data.data && data.data.data || null;
          if (!total || !rspData || !Array.isArray(rspData) || rspData.length < 1) {
            return {
              "results": [],
              "pagination": { "more": false }
            };
          }
          var results = [], i, item, more = false;
          if (rspData.length < limit) {
            more = false;
          } else {
            var page = params.page && parseInt(params.page) || 0;
            if (page < 1) { page = 1; }
            if (limit * page < total) {
              more = true;
            } else {
              more = false;
            }
          }
          for (i = 0; i < rspData.length; i++) {
            if (itemConverter) {
              item = itemConverter(i, rspData[i], rspData);
            } else {
              item = rspData[i];
            }
            results.push(item);
          }
          return {
            "results": results,
            "pagination": { "more": more }
          };
        } else {
          layer.alert(data && data.msg || '服务器错误，请稍后重试!', { title: '错误提示', icon: 0 });
          return {
            "results": [],
            "pagination": { "more": false }
          };
        }
      },
      error: function (jqXHR, textStatus, errorThrown) {
        layer.alert('网络错误，请稍后重试!', { title: '错误提示', icon: 0 });
      }
    },
  });
};

REGISTERSELECTONLINE;
            foreach ($selectOnlineFieldArr as $field) {
                $fieldName = empty($field['fieldName']) ? null : trim($field['fieldName']);
                $url = empty($field['url']) ? null : trim($field['url']);
                $searchFieldName = empty($field['searchFieldName']) ? null : trim($field['searchFieldName']);
                if (empty($fieldName) || empty($url) || empty($searchFieldName)) {
                    continue;
                }
                $placeholder = empty($field['placeholder']) ? null : trim($field['placeholder']);
                if (empty($placeholder)) {
                    $label = empty($field['label']) ? '' : trim($field['label']);
                    $placeholder = '请选择' . $label;
                }
                $width = empty($field['width']) ? '' : trim($field['width']);
                $itemConverter = empty($field['itemConverter']) ? null : trim($field['itemConverter']);
                if (empty($itemConverter)) {
                    $itemConverter = 'null';
                }
                $limit = empty($field['limit']) ? 0 : intval($field['limit']);
                $orderFieldName = empty($field['orderFieldName']) ? '' : trim($field['orderFieldName']);
                $orderDirection = empty($field['orderDirection']) ? 0 : intval($field['orderDirection']);
                echo 'registerSelectOnline(' . "'{$fieldName}'"
                    . ',' . "'{$url}'"
                    . ',' . "'{$searchFieldName}'"
                    . ',' . "'{$placeholder}'"
                    . ',' . "'{$width}'"
                    . ',' . $itemConverter
                    . ',' . $limit
                    . ',' . "'{$orderFieldName}'"
                    . ',' . $orderDirection
                    . ');' . "\n";
            }
        }
      ?>
      getSearchbarSearchData = function () {
        var searchbar = $('.wgx_table_wrapper .table_searchbar');
        var searchData = {};
        var searchFields = searchbar.find('.search_field');
        var i, jField, fieldName, inputType, inputVal;
        for (i = 0; i < searchFields.length; i++) {
          jField = $(searchFields[i]);
          fieldName = jField.data('fieldname');
          fieldName = fieldName && fieldName.trim() || null;
          if (!fieldName) {
            continue;
          }

          inputType = jField.data('inputtype');
          inputType = inputType && inputType.trim() || null;
          if (!inputType) {
            continue;
          }

          inputVal = null;
          switch (inputType) {
            case '<?php echo ListPageSearchInputBase::InputText; ?>':
            case '<?php echo ListPageSearchInputBase::InputNumber; ?>':
            case '<?php echo ListPageSearchInputBase::InputTel; ?>':
            case '<?php echo ListPageSearchInputBase::InputEmail; ?>':
              inputVal = jField.find('input[name="' + fieldName + '"]').val();
              inputVal = inputVal && inputVal.trim() || '';
              break;
            case '<?php echo ListPageSearchInputBase::InputSelect; ?>':
            case '<?php echo ListPageSearchInputBase::InputSelectOnline; ?>':
              inputVal = jField.find('select[name="' + fieldName + '"]').val();
              break;
            case '<?php echo ListPageSearchInputBase::InputCustomize; ?>':
              layer.alert(inputType + '控件还没有实现，请使用已经实现了的控件!', { title: '错误提示', icon: 0 });
              return false;
              break;
            default:
              layer.alert(inputType + '控件是无效的控件，请使用有效的控件!', { title: '错误提示', icon: 0 });
              return false;
              break;
          }
          searchData[fieldName] = inputVal;
        }
        return searchData;
      };
      pageDataTable = $('#page_data_table').DataTable({
        language: {
          url: '/wgx_admin_static/DataTables/DataTables-1.10.21/plugins/i18n/wgx_chinese.json'
        },
        dom: 'rit<"table_footer"<"length_pager"lp<"page_jumper">>i>', // lfrtip
        // initComplete: function (dtSettings, data) { // 改成了使用 init 事件
        //   var html = '<label>跳转到<input type="text" name="pageNum" />页</label><button class="jump_to_page">跳转</button>';
        //   $('.dataTables_wrapper .length_pager .page_jumper').html(html);
        // },
        // responsive: true,
        autoWidth: false,
        scrollX: false,

        paging: true,
        lengthChange: true,
        lengthMenu: [10, 25, 50, 100],
        // pageLength: 50,
        pagingType: 'simple_numbers',
        // displayStart: 50,

        searching: false,
        processing: true,
        serverSide: true,
        ajax: function (reqData, callback, dtSettings) {
          // console.log(reqData);
          var myReq = { _op_: 'listdata', _draw: reqData.draw, _limit: reqData.length, _offset: reqData.start, _orderFieldName: '', _orderDirection: 0 };
          if (reqData.order && Array.isArray(reqData.order) && reqData.order.length > 0) {
            var orderFieldName = pageDataTable.column(reqData.order[0].column).dataSrc();
            orderFieldName = orderFieldName && orderFieldName.toString().trim() || null;
            if (orderFieldName) {
              var orderDirection = reqData.order[0].dir;
              if (!orderDirection || orderDirection == 'desc') {
                orderDirection = 0;
              } else {
                orderDirection = 1;
              }
              myReq._orderFieldName = orderFieldName;
              myReq._orderDirection = orderDirection;
            }
          }

          var searchData = getSearchbarSearchData();
          if (searchData) {
            var k;
            for (k in searchData) {
              if (searchData.hasOwnProperty(k)) {
                myReq[k] = searchData[k];
              }
            }
          }

          $.ajax({
            method: 'GET',
            url: window.location.pathname,
            // contentType: 'application/json; charset=UTF-8',
            data: myReq,
            dataType: 'json',
            // beforeSend: function (jqXHR, settings) { },
            // complete: function (jqXHR, textStatus) { },
            success: function (data, textStatus, jqXHR) {
              if (data && data.code && parseInt(data.code) < 400) {
                callback(data.data);
              } else {
                var errMsg = data && data.msg || '服务器错误，请稍后重试!';
                callback({ draw: reqData.draw && parseInt(reqData.draw) || 0, recordsTotal: 0, recordsFiltered: 0, data: [], error: errMsg });
                layer.alert(errMsg, { title: '错误提示', icon: 0 });
              }
            },
            error: function (jqXHR, textStatus, errorThrown) {
              var errMsg = '网络错误，请稍后重试!';
              callback({ draw: reqData.draw && parseInt(reqData.draw) || 0, recordsTotal: 0, recordsFiltered: 0, data: [], error: errMsg });
              layer.alert(errMsg, { title: '错误提示', icon: 0 });
            },
          });
        },

        columns: [
        <?php
            $columnsCnt = 0;
            if ($rights && ($rights & AdminToMenuEntity::RightDelete) > 0) {
                echo <<<'SELECTCHECKBOXCOLUMN'
{
  title: '',
  data: null,
  width: '20px',
  render: function (data, type, row, meta) {
    return '';
  },
  orderable: false,
  className: 'select-checkbox',
},
SELECTCHECKBOXCOLUMN;
                echo "\n";
                $columnsCnt = 1;
            }

            $orderFieldName = $crud->getLpOrderFieldName();
            $orderFieldIndex = -1;
            $orderDirection = $crud->getLpOrderDirection();

            $crudColumnsCnt = 0;
            $fieldMap = $crud->getFieldMap();
            /**
             * @var string $fieldName
             * @var CrudField $field
             */
            foreach ($fieldMap as $fieldName => $field) {
                $showIn = intval($field->getShowIn());
                if (($showIn & CrudField::ShowInListPage) < 1) {
                    continue;
                }

                $width = $field->getLpWidth();
                $width = empty($width) ? null : trim($width);
                $isSortable = $field->getLpIsSortable();
                $render = $field->getLpRender();
                $className = $field->getLpClassName();
                $className = empty($className) ? null : trim($className);

                // cellType:        Cell type to be created for a column [no]
                // className:       Class to assign to each cell in the column [ok]
                // contentPadding:  Add padding to the text content used when calculating the optimal width for a table. [no] - 交给样式
                // createdCell:     Cell created callback to allow DOM manipulation [no]
                // data:            Set the data source for the column from the rows data object / array [ok]
                // defaultContent:  Set default, static, content for a column [no] - 交给后端
                // name:            Set a descriptive name for a column [no] - 用 className 就可以满足 address individual columns 的需要
                // orderData:       Define multiple column ordering as the default order for a column [no] - 后端排序, 所以不需要
                // orderDataType:   Live DOM sorting type assignment [no] - 后端排序, 所以不需要
                // orderSequence:   Order direction application sequence [no]
                // orderable:       Enable or disable ordering on this column [ok]
                // render:          Render (process) the data for use in the table [ok]
                // searchable:      Enable or disable search on the data in this column [no] - 交给 searchbar
                // title:           Set the column title [ok]
                // type:            Set the column type - used for filtering and sorting string processing [no] - 过滤和排序等都是后端处理，前端不需要知道数据格式
                // visible:         Enable or disable the display of this column [no] - 交给 显示/掩藏 列 按钮
                // width:           Column width assignment [ok]

                echo '{'
                    . ' title: "' . $field->getHName() . '"'
                    . ', data: ' . (!empty($render) && empty($isSortable) ? 'null' : '"' . $fieldName . '"')
                    . (empty($width) ? '' : ', width: "' . $width . '"')
                    . (empty($render) ? '' : ', render: ' . $render)
                    . ', orderable: ' . (empty($isSortable) ? 'false' : 'true')
                    . ', className: "column_' . trim($fieldName) . (empty($className) ? '' : " {$className}") . '"'
                    . ' },' . "\n";
                $columnsCnt++;
                $crudColumnsCnt++;
                if ($orderFieldName && $orderFieldName == $fieldName && !empty($isSortable)) {
                    $orderFieldIndex = $columnsCnt - 1;
                }
            }
            if ($crudColumnsCnt < 1) {
                // 这里抛出异常发生在 Http Headers 输出之后，会破坏正在返回给客户端的报文，
                // 但这种情况本不应该发生，所以这里还是选择抛出一个异常，为了反馈给开发人员，以便开发人员赶紧改正
                throw new \Exception('Crud设置错误，请添加 列表页(listpage) 字段');
            }
        ?>
        ],

        // 多列排序需要指定顺序，允许 table 多列排序的话会把事情弄复杂，
        // 提供2种方案,
        // 1: table 只允许单列排序, searchbar 提供列过滤搜索;
        // 这个方案 在 table 初始化的时候默认 id 列升序, 其它可排序列上的排序都由用户的交互产生, 所以也就不需要在 table 初始化的时候给那些可排序列指定默认顺序.
        // searchbar 提供列过滤搜索的意思, 例如，本意想 [是否展示在菜单栏中:desc],[父菜单:asc],[顺序:desc], 那么可以在 searchbar 提供 [是否展示在菜单栏中:(是,否)], [父菜单:(可选择父菜单的下拉列表)] 这 2 个列过滤搜索, 那么用户再在 table 中指定 [顺序:desc] 就可以一定程度上满足需求
        // 2: table 不允许排序, 在 searchbar 提供指定好顺序的列排序选择器 A(asc,desc), B(asc,desc), C(asc,desc), 例如: [是否展示在菜单栏中:(asc, desc)],[父菜单:(asc, desc)],[顺序:(asc, desc)]

        ordering: true,
        orderMulti: false,
        orderClasses: false,
        <?php
           if ($orderFieldIndex >= 0) {
               if (empty($orderDirection) || $orderDirection == 'desc') {
                   $orderDirection = 'desc';
               } else {
                   $orderDirection = 'asc';
               }
               echo "order: [[{$orderFieldIndex}, '" . $orderDirection . "']],\n";
           }
        ?>

        select: {
          blurable: false,
          // className: '',
          info: true,
          items: 'row',
          // selector: '',
          style: 'multi+shift',
          toggleable: 'true',
        }
      });
      // ----------
      pageDataTable.on('init', function (e, settings, json) {
        var html = '<label>跳转到<input type="text" name="pageNum" />页</label><button class="jump_to_page">跳转</button>';
        $('.dataTables_wrapper .length_pager .page_jumper').html(html);

        new $.fn.dataTable.Buttons(pageDataTable, {
          buttons: [
            {
              // action: '',
              // attr: '',
              // available: '',
              // className: '',
              // destroy: '',
              // enabled: '',
              extend: 'colvis',
              // init: '',
              // key: '',
              // name: '',
              // namespace: '',
              // tag: '',
              text: '<i class="far fa-eye"></i>',
              titleAttr: '显示/隐藏 列',
            },
            {
              extend: 'copy',
              text: '<i class="far fa-copy"></i>',
              titleAttr: '拷贝到剪贴板',
            },
            {
              extend: 'print',
              text: '<i class="fas fa-print"></i>',
              titleAttr: '打印',
            },
          ]
        });
        pageDataTable.buttons().container().appendTo('.wgx_table_wrapper .table_toolbar');
        var defaultColvisAction = pageDataTable.button('.dt-button.buttons-colvis.buttons-collection').action();
        pageDataTable.button('.dt-button.buttons-colvis.buttons-collection').action(function (e, dt, jBtn, config) {
          defaultColvisAction.call(this, e, dt, jBtn, config);
          var jDtButtons = $('.wgx_table_wrapper .table_toolbar .dt-buttons');
          jDtButtons.find('.dt-button-background').hide();
          var jDtButtonCollection = jDtButtons.find('.dt-button-collection');
          jDtButtonCollection.css('top', '38px').css('left', '0px');

          var jBtns = jDtButtonCollection.find('button.dt-button');
          jBtns.each(function (idx, ele) {
            var text = $(ele).text();
            text = text && text.trim() || null;
            if (!text) {
              $(ele).hide();
            }
          });
        });
      });
      <?php if ($rights && ($rights & AdminToMenuEntity::RightDelete) > 0) : ?>
      // ----------
      var updateTheadSelectCheckbox = function () {
        var rowLen = $('#page_data_table tbody tr').length;
        var selectedRowLen = $('#page_data_table tbody tr.selected').length;
        var jTheadTr = $('#page_data_table thead tr');
        jTheadTr.removeClass('all-selected');
        jTheadTr.removeClass('partial-selected');
        if (selectedRowLen && selectedRowLen > 0) {
          if (selectedRowLen == rowLen) {
            jTheadTr.addClass('all-selected');
          } else {
            jTheadTr.addClass('partial-selected');
          }
          $('.wgx_table_wrapper .table_toolbar .operate.op-delete-multi').attr('disabled', false);
        } else {
          $('.wgx_table_wrapper .table_toolbar .operate.op-delete-multi').attr('disabled', true);
        }
      };
      pageDataTable.on('select', function (e, dt, type, indexes) {
        updateTheadSelectCheckbox();
      });
      pageDataTable.on('deselect', function (e, dt, type, indexes) {
        updateTheadSelectCheckbox();
      });
      $('#page_data_table').on('click', 'thead tr th.select-checkbox', function (e) {
        var jTr = $(this).closest('tr');
        if (jTr.hasClass('all-selected')) {
          pageDataTable.rows().deselect();
        } else {
          pageDataTable.rows().select();
        }
      });
      pageDataTable.on('draw', function (e, settings) {
        updateTheadSelectCheckbox();
      });
      <?php endif; ?>
      // ----------
      $('.wgx_table_wrapper').on('click', '.dataTables_wrapper .table_footer .length_pager .page_jumper .jump_to_page', function (e) {
        e.preventDefault();
        e.stopPropagation();
        $(this).blur();

        var pageNum = $(this).closest('.page_jumper').find('input[name="pageNum"]').val();
        pageNum = pageNum && parseInt(pageNum) || 0;
        if (pageNum < 1) {
          return false;
        }
        pageDataTable.page(pageNum - 1).draw('page');
        return true;
      });
      $('.wgx_table_wrapper').on('click', '.operate', function (e) {
        var jThis = $(this);
        if (jThis.hasClass('op-search')) {
          e.preventDefault();
          e.stopPropagation();
          jThis.blur();

          pageDataTable.page(0).draw('page');
        } else if (jThis.hasClass('op-export')) {
          var myReq = { _op_: 'export', _orderFieldName: '', _orderDirection: 0 };
          var tableOrder = pageDataTable.order();
          // console.log(tableOrder);
          if (tableOrder && Array.isArray(tableOrder) && tableOrder.length > 0) {
            var orderFieldName = pageDataTable.column(tableOrder[0][0] || 0).dataSrc();
            orderFieldName = orderFieldName && orderFieldName.toString().trim() || null;
            if (orderFieldName) {
              var orderDirection = tableOrder[0][1];
              if (!orderDirection || orderDirection == 'desc') {
                orderDirection = 0;
              } else {
                orderDirection = 1;
              }
              myReq._orderFieldName = orderFieldName;
              myReq._orderDirection = orderDirection;
            }
          }

          var searchData = getSearchbarSearchData();
          if (searchData) {
            var k;
            for (k in searchData) {
              if (searchData.hasOwnProperty(k)) {
                myReq[k] = searchData[k];
              }
            }
          }
          var exportUrl = window.location.pathname + '?' + $.param(myReq);
          jThis.attr('href', exportUrl);
          return true;
        } else if (jThis.hasClass('op-create')) {
          var target = jThis.data('target');
          target = target && target.trim() || '';
          if (target == 'layer') {
            e.preventDefault();
            e.stopPropagation();
            jThis.blur();

            var opts = {
              type: 2,
              title: '新增',
              content: jThis.attr('href'),
              offset: 'auto',
              closeBtn: 1,
              shade: [0.5, '#000'],
              shadeClose: false,
              time: 0,
              // id: '',
              anim: 0,
              maxmin: true,
              fixed: true,
              resize: true,
              // scrollbar: true,
              // move: '.topbar',
              moveOut: false,
            };
            var width = jThis.data('width');
            width = width && width.trim() || null;
            var height = jThis.data('height');
            height = height && height.trim() || null;
            if (width && height) {
              opts['area'] = [width, height];
            } else if (width) {
              opts['area'] = width;
            }

            layer.open(opts);
          } else {
            return true;
          }
        } else if (jThis.hasClass('op-delete-multi')) {
          e.preventDefault();
          e.stopPropagation();
          jThis.blur();

          var selectedRows = $('#page_data_table tbody tr.selected');
          if (selectedRows.length < 1) {
            return;
          }

          var ids = [], id, rowData;
          selectedRows.each(function (idx, ele) {
            rowData = pageDataTable.row(ele).data();
            id = rowData && rowData.id && parseInt(rowData.id) || null;
            if (id) {
              ids.push(id);
            }
          });
          if (ids.length < 1) {
            return;
          }

          layer.confirm('确定要删除选中的行吗？', { title: '确定吗？', icon: 3 }, function (layerIdx, layerObj) {
            // console.log(layerIdx, layerObj);
            layer.close(layerIdx);
            var loading = layer.load(2);
            $.ajax({
              method: 'DELETE',
              url: window.location.pathname + '?id=' + ids.join(','),
              // contentType: 'application/json; charset=UTF-8',
              // data: JSON.stringify(data),
              dataType: 'json',
              // beforeSend: function (jqXHR, settings) { },
              // complete: function (jqXHR, textStatus) { },
              success: function (data, textStatus, jqXHR) {
                layer.close(loading);
                if (data && data.code && parseInt(data.code) < 400) {
                  window.location.reload(true);
                } else {
                  layer.alert(data && data.msg || '服务器错误，请稍后重试!', { title: '错误提示', icon: 0 });
                }
              },
              error: function (jqXHR, textStatus, errorThrown) {
                layer.close(loading);
                layer.alert('网络错误，请稍后重试!', { title: '错误提示', icon: 0 });
              },
            });
          });
        } else {
          var tr = jThis.closest('#page_data_table tr');
          var rowData = tr && tr.length > 0 ? pageDataTable.row(tr).data() : null;
          var id = rowData && rowData.id && parseInt(rowData.id) || 0;
          if (id) {
            if (jThis.hasClass('op-read')) {
              var readUrl = window.location.pathname + '?_op_=readpage&id=' + id;

              var target = jThis.data('target');
              target = target && target.trim() || '';
              if (target == 'layer') {
                e.preventDefault();
                e.stopPropagation();
                jThis.blur();

                var opts = {
                  type: 2,
                  title: jThis.attr('title') || '查看',
                  content: readUrl,
                  offset: 'auto',
                  closeBtn: 1,
                  shade: [0.5, '#000'],
                  shadeClose: false,
                  time: 0,
                  // id: '',
                  anim: 0,
                  maxmin: true,
                  fixed: true,
                  resize: true,
                  // scrollbar: true,
                  // move: '.topbar',
                  moveOut: false,
                };
                var width = jThis.data('width');
                width = width && width.trim() || null;
                var height = jThis.data('height');
                height = height && height.trim() || null;
                if (width && height) {
                  opts['area'] = [width, height];
                } else if (width) {
                  opts['area'] = width;
                }

                layer.open(opts);
              } else {
                jThis.attr('href', readUrl);
                return true;
              }
            } else if (jThis.hasClass('op-edit')) {
              var editUrl = window.location.pathname + '?_op_=editpage&id=' + id;

              var target = jThis.data('target');
              target = target && target.trim() || '';
              if (target == 'layer') {
                e.preventDefault();
                e.stopPropagation();
                jThis.blur();

                var opts = {
                  type: 2,
                  title: jThis.attr('title') || '修改',
                  content: editUrl,
                  offset: 'auto',
                  closeBtn: 1,
                  shade: [0.5, '#000'],
                  shadeClose: false,
                  time: 0,
                  // id: '',
                  anim: 0,
                  maxmin: true,
                  fixed: true,
                  resize: true,
                  // scrollbar: true,
                  // move: '.topbar',
                  moveOut: false,
                };
                var width = jThis.data('width');
                width = width && width.trim() || null;
                var height = jThis.data('height');
                height = height && height.trim() || null;
                if (width && height) {
                  opts['area'] = [width, height];
                } else if (width) {
                  opts['area'] = width;
                }

                layer.open(opts);
              } else {
                jThis.attr('href', editUrl);
                return true;
              }
            } else if (jThis.hasClass('op-delete')) {
              e.preventDefault();
              e.stopPropagation();
              jThis.blur();

              layer.confirm('确定要删除此行吗？', { title: '确定吗？', icon: 3 }, function (layerIdx, layerObj) {
                // console.log(layerIdx, layerObj);
                layer.close(layerIdx);
                var loading = layer.load(2);
                $.ajax({
                  method: 'DELETE',
                  url: window.location.pathname + '?id=' + id,
                  // contentType: 'application/json; charset=UTF-8',
                  // data: JSON.stringify(data),
                  dataType: 'json',
                  // beforeSend: function (jqXHR, settings) { },
                  // complete: function (jqXHR, textStatus) { },
                  success: function (data, textStatus, jqXHR) {
                    layer.close(loading);
                    if (data && data.code && parseInt(data.code) < 400) {
                      window.location.reload(true);
                    } else {
                      layer.alert(data && data.msg || '服务器错误，请稍后重试!', { title: '错误提示', icon: 0 });
                    }
                  },
                  error: function (jqXHR, textStatus, errorThrown) {
                    layer.close(loading);
                    layer.alert('网络错误，请稍后重试!', { title: '错误提示', icon: 0 });
                  },
                });
              });
            }
            // else {
            //   e.preventDefault();
            //   e.stopPropagation();
            //   jThis.blur();
            // }
          }
        }
      });
    });
    <?php
    $jsInlineFileMap = $crud->getFileMap(Crud::PageListPage, Crud::FileJsInline);
    if ($jsInlineFileMap) {
        foreach ($jsInlineFileMap as $file => $flag) {
            if ($flag) {
                require $file;
            }
        }
    }
    ?>
  </script>
</body>

</html>
